package org.demo.es.service.impl;

import org.demo.es.service.DocumentService;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.BulkRequest;
import co.elastic.clients.elasticsearch.core.GetResponse;
import co.elastic.clients.elasticsearch.core.IndexRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * DocumentService实现类
 * 用于定义ElasticSearch的文档的增删改查操作
 * @author moxiaoli
 */
@Slf4j
@Service
public class DocumentServiceImpl implements DocumentService {

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    @Override
    public <T> boolean addDocument(String index, String id, T data) {
        IndexRequest<T> request = IndexRequest.of(i -> i
                .index(index)
                .id(id)
                .document(data)
//                .version(1L)
        );
        try {
            elasticsearchClient.index(request);
        }catch (IOException e){
            log.error("文档添加失败：{}", e.getMessage());
            return false;
        }
        log.info("文档的索引名称：{}", index);
        log.info("新增的文档id：{}", id);
        log.info("新增的文档数据：{}", data);
        return true;
    }

    @Override
    public boolean deleteDocument(String index, String id) {
        try {
            elasticsearchClient.delete(d -> d
                    .index(index)
                    .id(id)
            );
        } catch (IOException e) {
            log.error("文档删除失败：{}", e.getMessage());
            return false;
        }
        log.info("删除的文档索引名称：{}", index);
        log.info("删除的文档id：{}", id);
        return true;
    }

    @Override
    public <T> boolean updateDocument(String index, String id, T data, Class<T> clazz) {
        try {
            elasticsearchClient.update(u -> u
                    .index(index)
                    .id(id)
                    .upsert(data),
                    clazz
            );
        } catch (IOException e) {
            log.error("文档更新失败：{}", e.getMessage());
            return false;
        }
        log.info("更新的文档索引名称：{}", index);
        log.info("更新的文档id：{}", id);
        log.info("更新的文档数据：{}", data);
        return true;
    }

    @Override
    public <T> T getDocument(String index, String id, Class<T> clazz) {
        try {
            GetResponse<T> response = elasticsearchClient.get(g -> g
                            .index(index)
                            .id(id),
                    clazz
            );
            if (response.found()) {
                // 获取文档数据
                T t = response.source();
                log.info("查询的文档索引名称：{}", index);
                log.info("查询的文档id：{}", id);
                log.info("查询的文档数据：{}", t);
                return t;
            } else {
                log.info("查询的文档不存在");
            }
        }catch (IOException e){
            log.error("文档查询失败：{}", e.getMessage());
        }
        return null;
    }

    @Override
    public boolean isDocumentExist(String index, String id) {
        try {
            boolean flag = elasticsearchClient.exists(e -> e
                    .index(index)
                    .id(id)
            ).value();
            if (flag) {
                log.info("查询的文档索引名称：{}", index);
                log.info("查询的文档id：{}", id);
                return true;
            } else {
                log.info("查询的文档不存在");
                return false;
            }
        } catch (IOException e) {
            log.error("文档查询失败：{}", e.getMessage());
            return false;
        }
    }

    @Override
    public <T> boolean bulkAddDocument(String index, List<Map<String,T>> data) {
        BulkRequest.Builder br = new BulkRequest.Builder();
        for (Map<String,T> t : data) {
            br.operations(op->op.index(idx->idx
                    .index(index)
                    .id(t.get("id").toString())
                    .document(t.get("data"))
            ));
        }
        try {
            elasticsearchClient.bulk(br.build());
        } catch (IOException e) {
            log.error("文档批量添加失败：{}", e.getMessage());
            return false;
        }
        log.info("批量添加的文档索引名称：{}", index);
        log.info("批量添加的文档数据：{}", data);
        return true;
    }

    @Override
    public boolean bulkDeleteDocument(String index, List<String> ids) {
        BulkRequest.Builder br = new BulkRequest.Builder();
        for (String id : ids) {
            br.operations(op->op.delete(d->d
                    .index(index)
                    .id(id)
            ));
        }
        try {
            elasticsearchClient.bulk(br.build());
        } catch (IOException e) {
            log.error("文档批量删除失败：{}", e.getMessage());
            return false;
        }
        log.info("批量删除的文档索引名称：{}", index);
        log.info("批量删除的文档id：{}", ids);
        return true;
    }

    @Override
    public <T> boolean bulkUpdateDocument(String index, List<Map<String,T>> data, Class<T> clazz) {
        return false;
    }

    @Override
    public <T> List<T> bulkGetDocument(String index, List<String> ids, Class<T> clazz) {
        return null;
    }

}
